using System;
using System.Collections.Generic;
using System.Text;

namespace XGAE.Framework.Extensions
{
    /// <summary>
    /// Return a noisy value as a function of an input.  This is parametric noise producing 
    /// pseudo-random function over a one dimensional parameter. 
    /// </summary>
    public struct Perlin
    {
        private int _BitShift;
        private int _Prime1;
        private int _Prime2;
        private int _Prime3;

        public Perlin(int BitShift, int Prime1, int Prime2, int Prime3)
        {          
            _BitShift = BitShift;
            _Prime1 = Prime1;
            _Prime2 = Prime2;
            _Prime3 = Prime3;
        }

        /// <summary>
        /// Compute a pseudo-random float of unit range using simple primitive operations.
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public float Raw(int x)
        {
            // jumble up the bits to get a bit more variety
            int y = (x<<_BitShift) ^ x;
            // multiply the value by prime numbers to get pseudo-random results
            // the vale returned is within unit range around zero
            return (1.0f - ((y * (y * y * _Prime1 + _Prime2) + _Prime3) & 0x7fffffff) / 1073741824.0f);
    	
        }

        /// <summary>
        /// Return a smooth interpolation of the raw noise function provided.  
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public float Value(float x)
        {
            // find the integer part of the number
	        int i = (int)x;
            // and determine the fraction
	        float f = x - (float)i;
            // call the integer noise function twice and interpolate linearly
	        return Raw(i) * (1-f) + Raw(i+1) * f;

        }
    }
}
